from Database import DataModel
from utils.expand import *
import os
from openai import OpenAI
from os import getenv
from config.config import Config
import requests
import json


def getTotalQuestion(question: str):
    total_question = f"""step1、你是一名宏观经济数据分析专家，善于宏观经济指标理解、计算及数据分析step2、请根据{question}，如果能，则给出本地数据查询的SQL脚本。如果不能从本地获取数据或者SQL部分提示：提供的表结构信息不足以生成 sql 查询，SQL就返回值\"internet\" 
step3、背景信息之本地数据库表结构说明
数据库类型: 
   MySQL
数据库名:
   data
表结构定义:
   表:
      表名: weo_data
      中文表名:数据表
      注释: 各国指标数据信息
      表类型: 增量表
      表字段:
        字段名称:weo_country_code; 字段类型:    
               varchar(40); 字段描述: WEO国家代码
        字段名称:iso; 字段类型: varchar(10); 字段描述: 国际标准
        字段名称:norm;  字段类型: varchar(20); 字段描述: 指标名称，此为一个枚举类型，具体内容如下
 NGDP_R：   国内生产总值（实际）,
 NGDP_RPCH:  国内生产总值（年增长率）,
 NGDP:   国内生产总值（名义本币）,
 NGDPD:  国内生产总值（名义美元）,
 PPPGDP: 国内生产总值，当前价格,
 NGDP_D: 国内生产总值平减指数,
 NGDPRPC:    按不变价格计算的人均国内生产总值,
 NGDPRPPPPC: 按不变价格计算的人均国内生产总值,
 NGDPPC: 人均国内生产总值(当前本币价格),
 NGDPDPC:    人均国内生产总值(当前美元价格),
 PPPPC:  人均国内生产总值(购买力平价美元),
 NGAP_NPGDP: 产出缺口占潜在GDP的百分比,
 PPPSH:  基于购买力平价的国内生产总值在世界总量中的份额,
 PPPEX:  隐含PPP转换率,
 NID_NGDP:   总投资占GDP比例,
 NGSD_NGDP:  国民储蓄总额占GDP比例,
 PCPI:   通货膨胀、平均消费价格,
 PCPIPCH:    通货膨胀、平均消费价格同比变化,
 PCPIE:  通货膨胀、期末消费价格,
 PCPIEPCH:   通货膨胀、期末消费价格同比变化,
 TM_RPCH:    进口总额的实际百分比变化,
 TMG_RPCH:   商品进口总额的实际百分比变化,
 TX_RPCH:    出口总额的实际百分比变化,
 TXG_RPCH:   商品出口总额的实际百分比变化,
 LUR:    失业率,
 LE: 工作,
 LP: 人口,
 GGR:    政府一般收入,
 GGR_NGDP:   政府一般收入占GDP比例,
 GGX:    一般政府总支出,
 GGX_NGDP:   一般政府总支出占GDP比例,
 GGXCNL: 一般政府净借贷,
 GGXCNL_NGDP:    一般政府净借贷占GDP比例,
 GGSB:   结构性预算余额,
 GGSB_NPGDP: 结构性预算余额占GDP比例,
 GGXONLB:    一般政府初级净借贷,
 GGXONLB_NGDP:   一般政府初级净借贷占GDP比例,
 GGXWDN: 一般政府净债务,
 GGXWDN_NGDP:    一般政府净债务占GDP比例,
 GGXWDG: 一般政府总债务,
 GGXWDG_NGDP:    一般政府总债务占GDP比例,
 NGDP_FY:    对应财政年度的国内生产总值，当前价格,
 BCA:    经常账户余额,
 BCA_NGDPD:  经常账户余额占GDP比例\
 字段名称:country; 字段类型: varchar(40); 字段描述: 国家名称
                        字段名称:units; 字段类型: varchar(200); 字段描述: 单位
                        字段名称:scale; 字段类型: varchar(200); 字段描述: 规模
                        字段名称:year; 字段类型: varchar(200); 字段描述: 数据年份
                        字段名称:data_value; 字段类型: varchar(200); 字段描述: 年度数据
                        字段名称:estimates_start_after; 字段类型: varchar(200); 字段描述: 测算开始时间 
              约束:
            1. response data must be plain text and format must keep as below : {{"thoughts": "thoughts summary to say to user","sql": "SQL Query to run","display_type": "Data display method"}}
            2. please check the response data and keep plain text， please convert format into plain text if response data is json objects.
            3. country data of answer data must be English, country field filtering criteria  uses lowercase function must be lowercase format
            4. 请根据{question}理解用户意图，使用给出表结构定义创建一个语法正确的 mysql sql，如果不需要sql，则直接回答用户问题。

            5. 如果不能从本地获取数据或者SQL部分提示：提供的表结构信息不足以生成 sql 查询，SQL就返回值\"internet\"
            6. 只能使用表结构信息中提供的表来生成 sql，如果无法根据提供的表结构中生成 sql ，请说：“提供的表结构信息不足以生成 sql 查询。” 禁止随意捏造信息，禁止改变表原始字段名。
            7. 请注意生成SQL时不要弄错表和列的关系。
            8. 请检查SQL的正确性，并保证正确的情况下优化查询性能。
            9. 生成的SQL必须严格遵循MySQL的语法和特性，禁止使用MySQL不支持的语法、特性、函数或关键字，如FILTER子句、WITH子句、CTE（Common Table Expression）查询结构、REAL数据类型等,尽可能的避免使用as关键字。
            10. 生成的SQL必须返回year字段，country字段，norm字段，data_value字段，units字段
            11. 默认display_type为table，如果{question}中涉及到对比display_type为bar，如果涉及趋势display_type为trend，如果涉及相关性display_type为scatter，如果涉及占比display_type为pie
 """
    return total_question


def check_field(attribute_list: list) -> bool:
    if (
       'norm' in attribute_list and 'country' in attribute_list and 'units' in attribute_list and 'year' in attribute_list and 'data_value' in attribute_list):
        return True
    else:
        return False


@timecost
def get_thought_result_gpt4o(question: str, data_value: str) -> str:
    os.environ['OPENROUTER_API_KEY'] = "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"
    ask_message = get_ask_message(question,data_value)

    # gets API Key from environment variable OPENAI_API_KEY
    client = OpenAI(
        base_url="https://openrouter.ai/api/v1",
        api_key=getenv("OPENROUTER_API_KEY"),
    )

    completion = client.chat.completions.create(
        extra_headers={
        },
        model="openai/gpt-4o",
        messages=ask_message
    )
    return completion.choices[0].message.content

@timecost
def get_thought_result_qwen(question: str, data_value: str) -> str:
    os.environ["DASHSCOPE_API_KEY"] = Config.DASHSCOPE_API_KEY
    from langchain_community.chat_models.tongyi import ChatTongyi
    llm = ChatTongyi()
    llm.model_name = 'qwen-long'
    ask_message = get_ask_message(question, data_value)
    response = llm.invoke(ask_message).content
    return response
@timecost
def get_relevlance_result_qwen(question: str) ->str:

    os.environ["DASHSCOPE_API_KEY"] = Config.DASHSCOPE_API_KEY
    from langchain_community.chat_models.tongyi import ChatTongyi
    llm = ChatTongyi()
    llm.model_name = 'qwen-long'
    ask_message = []
    system_question = {'role': 'system', 'content': get_relevance_question(question)}
    user_question = {'role': 'user', 'content': question}
    ask_message.append(system_question)
    ask_message.append(user_question)
    response = llm.invoke(ask_message).content
    return response

def get_ask_message(question: str, data_value: str) -> []:
    promot = f"""1. if user question {question}is about “how much” or "how many" or values of Economic indicators. Please reply question as below: 请解析{data_value}json数据，如果units为货币，量级单位为十亿，无需显示json解析过程，显示通过该数据精要说明该指标数据的重大意义; if the question is about comparision. Please reply question as below: 请解析json数据，如果units为货币，计数单位为十亿，无需显示json解析过程，显示通过该指标数据对比得出精华结论; if the question is about trend. Please reply question as below: 请解析json数据，如果units为货币，计数单位为十亿，无需显示json解析过程，显示通过指标数据趋势分析得出精华结论; if the question is about Correlation. Please reply question as below: 请解析json数据，如果units为货币，计数单位为十亿，无需显示json解析过程，显示通过多个指标数据相关性分析得出精华结论; if the question is about proportion. Please reply question as below: 请解析json数据，如果units为货币，计数单位为十亿，无需显示json解析过程，显示通过多组数据对比以及单组数据对总数据的占比情况分析得出精华结论 2. only show conclusion part for the response. 3. 如果计数单位为十亿 ，请转换为 亿 描述。 """
    ask_message = []
    system_question = {'role': 'system', 'content': promot}
    user_question = {'role': 'user', 'content': question}
    ask_message.append(system_question)
    ask_message.append(user_question)
    return ask_message

@timecost
def invoke_dify(question:str,apikey: str) -> []:
    result_data = []
    try:
        url = 'http://81.68.216.231:8099/v1/workflows/run'
        headers = {
            'User-Agent': 'PostmanRuntime/7.29.0',
            'Authorization': 'Bearer ' + apikey,
            'Content-Type': 'application/json'
        }

        data = {
            'inputs': {'user_qst': question},
            'response_mode': 'blocking',
            'user': 'wubing'
        }

        response = requests.post(url, json=data, headers=headers).json()
        invoke_data = response.get('data').get('outputs').get('data_outer')

        logging.info(f'从谷歌获取数据，返回结果为:{invoke_data}')
        json_data = json.loads(invoke_data)
        for item in json_data:
            tmp_data = DataModel(country=item.get('country'), year=item.get('year'),norm = item.get('norm'), units = item.get('units'), data_value = item.get('data_value'))
            result_data.append(tmp_data)
    except Exception as e:
        print(str(e))
        logging.error('使用谷歌api获取数据出现异常')

    return result_data



def get_relevance_question(question:str)->str:
    total_question = f"""step1. 你是一经济学家和语言学家，善常分析文字语言及经济问题。
step2. 如果{question}描述中包含经济等关键字或者问题中是否有关经济指标或者间接影响经济的指标则返回值为Y，否则返回值为N。
比如， 用户问题：2023年中国失业率。 回答：Y。
比如，用户问题：2023年中国近5年人口。 回答：Y。
step3. 如果问题描述中包含以下指标名，回答Y：
NGDP_R：   国内生产总值（实际）,
NGDP_RPCH:  国内生产总值（年增长率）,
NGDP:   国内生产总值（名义本币）,
NGDPD:  国内生产总值（名义美元）,
PPPGDP: 国内生产总值，当前价格,
NGDP_D: 国内生产总值平减指数,
NGDPRPC:    按不变价格计算的人均国内生产总值,
NGDPRPPPPC: 按不变价格计算的人均国内生产总值,
NGDPPC: 人均国内生产总值(当前本币价格),
NGDPDPC:    人均国内生产总值(当前美元价格),
PPPPC:  人均国内生产总值(购买力平价美元),
NGAP_NPGDP: 产出缺口占潜在GDP的百分比,
PPPSH:  基于购买力平价的国内生产总值在世界总量中的份额,
PPPEX:  隐含PPP转换率,
NID_NGDP:   总投资占GDP比例,
NGSD_NGDP:  国民储蓄总额占GDP比例,
PCPI:   通货膨胀、平均消费价格,
PCPIPCH:    通货膨胀、平均消费价格同比变化,
PCPIE:  通货膨胀、期末消费价格,
PCPIEPCH:   通货膨胀、期末消费价格同比变化,
TM_RPCH:    进口总额的实际百分比变化,
TMG_RPCH:   商品进口总额的实际百分比变化,
TX_RPCH:    出口总额的实际百分比变化,
TXG_RPCH:   商品出口总额的实际百分比变化,
LUR:    失业率,
LE: 工作,
LP: 人口,
GGR:    政府一般收入,
GGR_NGDP:   政府一般收入占GDP比例,
GGX:    一般政府总支出,
GGX_NGDP:   一般政府总支出占GDP比例,
GGXCNL: 一般政府净借贷,
GGXCNL_NGDP:    一般政府净借贷占GDP比例,
GGSB:   结构性预算余额,
GGSB_NPGDP: 结构性预算余额占GDP比例,
GGXONLB:    一般政府初级净借贷,
GGXONLB_NGDP:   一般政府初级净借贷占GDP比例,
GGXWDN: 一般政府净债务,
GGXWDN_NGDP:    一般政府净债务占GDP比例,
GGXWDG: 一般政府总债务,
GGXWDG_NGDP:    一般政府总债务占GDP比例,
NGDP_FY:    对应财政年度的国内生产总值，当前价格,
BCA:    经常账户余额,
BCA_NGDPD:  经常账户余额占GDP比例
step4. 不需要解释和提示信息，无需判断是否合理，只需回答Y或者N。
"""
    return total_question